package com.bgds.sys.data.iXCom29d.gateway.impl;

import com.alibaba.fastjson.JSON;
import com.bgds.sys.data.iXCom29d.gateway.vo.BaoxinGatewayVo;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
import com.cisdi.data.sdk.param.ListenSocketParam;
import com.cisdi.data.sdk.vo.GatewayVo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Smiling
 * @description: TODO
 * @date 2021/3/28  14:43
 */
public class BaoxinTcpIoService implements TcpIoService {
    private static Logger logger = LoggerFactory.getLogger(BaoxinTcpIoService.class);
    private static final int BIZGROUPSIZE = 2;
    private BaoxinGatewayVo conf;
    private SessionFactory sessionFactory;
    private ServerBootstrap bootstrap;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ChannelInitializer<Channel> channelInitializer;

    public BaoxinTcpIoService() {

    }

    @Override
    public void init(GatewayVo conf, SessionFactory sessionFactory, ChannelInitializer<Channel> channelInitializer) {
        this.conf =(BaoxinGatewayVo)conf;
        this.sessionFactory = sessionFactory;
        this.channelInitializer = channelInitializer;
    }
    @Override
    public boolean open() {
        if (this.conf != null && this.sessionFactory != null) {
            if (this.bossGroup != null && this.workerGroup != null) {
                return true;
            } else {
                boolean tryStart = this.tryStart();
                return tryStart;
            }
        } else {
            throw new BusinessException("未初始化配置。");
        }
    }
    @Override
    public boolean close() {
        if (this.conf != null && this.sessionFactory != null) {
            if (this.bootstrap == null && this.workerGroup == null) {
                return true;
            } else {
                boolean tryClose = this.tryClose();
                return tryClose;
            }
        } else {
            throw new BusinessException("未初始化配置。");
        }
    }

    private boolean tryStart() {
        boolean result = false;
        ListenSocketParam socketParam = JSON.parseObject(this.conf.getParameter(), ListenSocketParam.class);
        try {
            this.bootstrap = new ServerBootstrap();
            this.bossGroup = new NioEventLoopGroup(5);
            this.workerGroup = new NioEventLoopGroup(socketParam.getThreadSize());
            this.bootstrap.group(this.bossGroup, this.workerGroup);
            (this.bootstrap.channel(NioServerSocketChannel.class)).childHandler(this.channelInitializer);
            ((this.bootstrap.option(ChannelOption.SO_BACKLOG, 128)).option(ChannelOption.SO_REUSEADDR, true)).childOption(ChannelOption.TCP_NODELAY, true).childOption(ChannelOption.SO_KEEPALIVE, true);
            int[] ports=this.conf.getPorts();
            for(int port:ports){
                ChannelFuture future = this.bootstrap.bind(socketParam.getListenIp(), port).sync();
                future.channel().closeFuture().addListener(ChannelFutureListener-> future.channel().close());
                logger.info("Successfully start the server {}:{}", socketParam.getListenIp(), port);
            }
            result = true;
        } catch (Exception var5) {
            logger.error("The server {}:{} start failure", new Object[]{socketParam.getListenIp(), socketParam.getListenPort(), var5});
            this.close();
        }

        return result;
    }

    private boolean tryClose() {
        boolean result = false;
        ListenSocketParam socketParam = JSON.parseObject(this.conf.getParameter(), ListenSocketParam.class);

        try {
            if (null != this.bossGroup) {
                this.bossGroup.shutdownGracefully().sync();
            }

            if (null != this.workerGroup) {
                this.workerGroup.shutdownGracefully().sync();
            }

            this.bossGroup = null;
            this.workerGroup = null;
            result = true;
        } catch (Exception var4) {
            logger.error("the server {}:{} caught exception while close", new Object[]{socketParam.getListenIp(), socketParam.getListenPort(), var4});
        }

        return result;
    }
}